import axios from 'axios'

/* 
    {
        dataKey: 'data',
        commonParams: {},
        beforeRequest: () => {},
        isOk: () => true,
        error: () => {},
        logout: () => {},
        config: {},
        headers: {},
    }
*/

if (axios.VERSION !== '1.6.7') {
    console.warn('版本不对，可能有异常')
}

function Axios(options = {}) {
    const CancelToken = axios.CancelToken
    window.AXIOS_CANCELS = window.AXIOS_CANCELS || {}
    
    const isWebpack = typeof process === 'object'
    const reactBase = 'REACT_APP'
    const vueBase = 'VUE_APP'

    const baseURL = isWebpack ? 
        process.env[`${reactBase}_BASEURL`] || process.env[`${vueBase}_BASEURL`] :
        '/'
    const timeout = isWebpack ?
        process.env[`${reactBase}_TIMEOUT`] || process.env[`${vueBase}_TIMEOUT`] :
        0

    const Http = axios.create({
        method: 'post',
        timeout: options.timeout || timeout || 0,
        baseURL: options.baseURL || baseURL || '',
        headers: {
            'Content-Type': 'application/json',
            ...options.headers
        },
    })

    Http.interceptors.request.use(
        config => {
            let commonParams = {}
            if (options.beforeRequest) {
                options.beforeRequest(config)
            } else {
                const sKeys = Object.keys(sessionStorage)
                for (let i=0; i<sKeys.length - 1; i++) {
                    if (sKeys[i].toLocaleLowerCase().includes('token')) {
                        config.headers[sKeys[i]] = sessionStorage[sKeys[i]]
                        commonParams = {
                            [sKeys[i]]: sessionStorage[sKeys[i]]
                        }
                    }
                }
                const lKeys = Object.keys(localStorage)
                for (let i=0; i<lKeys.length - 1; i++) {
                    if (lKeys[i].toLocaleLowerCase().includes('token')) {
                        config.headers[lKeys[i]] = localStorage[lKeys[i]]
                        commonParams = {
                            [lKeys[i]]: sessionStorage[lKeys[i]]
                        }
                    }
                }
            }

            const isParams = config.method.toLowerCase()==='get'
            let payload = isParams ? config.params || {} : config.data || {}
            const isDataArray = Array.isArray(payload)

            if (payload.cancelToken) {
                config.cancelToken = new CancelToken(function (c) {
                    window.AXIOS_CANCELS[payload.cancelToken] = function() {
                        c && c()
                        delete window.AXIOS_CANCELS[config.cancelTokenKey]
                    }
                    // const params = config.params;
                    config.cancelTokenKey = payload.cancelToken
                    delete payload.cancelToken
                })
            }
            payload = (isDataArray || payload instanceof FormData) ? payload : {
                ...options.commonParams,
                ...payload,
            }
            if (isParams) {
                config.params = payload
            } else {
                config.data = payload
            }
            if (options.finalBeforeRequest) {
                options.finalBeforeRequest(config)
            }
            return config
        },
        error => {
            return Promise.reject(error)
        }
    )

    Http.interceptors.response.use(
        res => {
            if (res.config.cancelTokenKey) {
                delete window.AXIOS_CANCELS[res.config.cancelTokenKey]
            }
            if (res.headers['content-disposition']) {
                const { baseURL, url } = res.config
                sessionStorage[`wbiokr_${url.replace(baseURL, '')}`] = JSON.stringify(decodeURIComponent(res.headers['content-disposition']).split(';').reduce((a, b)=> ({ ...a, [String(b.split('=')[0]).toLowerCase()]: b.split('=')[1]}), {}))
            }
            if (
                res.config.url.includes('wjump=1')
                || String(res.config.responseType).toLocaleLowerCase() === 'blob'
                || String(res.config.responseType).toLocaleLowerCase() === 'arraybuffer'
            ) {
                return options.blobAfterRequest ? options.blobAfterRequest(res.data, res.config) : res.data
            }

            const data = options.finalAfterRequest ? options.finalAfterRequest(res.data, res.config) : res.data
            
            if (isOk(data)) {
                return (data[options.dataKey || 'data'])
            }else {
                const msg = data.message || data.msg || data.errorMsg || data.errorMessage || data.errormessage || data.errormsg
                !!msg && options.error && !res.config.url.includes('wnomsg=1') && options.error(msg)
                return Promise.reject(data)
            }
            
        },
        error => {
            if (error.response) {
                let data = error.response.data
                switch (error.response.code || error.response.status) {
                    case 401:
                        options.error && options.error('未授权，请重新登录')
                        options.logout && options.logout()
                        break
                    case 404:
                        options.error && options.error('接口不存在')
                        break
                    case 403:
                        options.error && options.error('拒绝访问')
                        break
                    case 504:
                        options.error && options.error('网络超时')
                        break
                    case 500:
                        if (String(data.message).toLowerCase().includes('token失效')) {
                            options.logout && options.logout()
                        }
                        break
                    default:
                        options.error && options.error(data.message || data.msg || data.errorMsg || data.errorMessage || '接口出问题')
                }
            } else {
                // options.error && options.error(error.message)
            }
            return Promise.reject(error)
        }
    )

    function isOk(res) {
        if(typeof options.isOk === 'function') {
            return options.isOk(res)
        }
        const v = res.hasOwnProperty('code') ? res.code : res.hasOwnProperty('status') ? res.status : ''
        return v === 200 || v === 0
    }

    return Http
}

export default Axios
